#ifndef __NCENTER_H__
#define __NCENTER_H__

#include <string>

#include "Observer.h"

class NCenter
{
	typedef std::multimap< std::wstring, IObserver* >				ObsType;
	typedef std::multimap< std::wstring, IObserver* >::iterator		ItObsType;

	typedef std::multimap< std::wstring, IParam* >					PostType;
	typedef std::multimap< std::wstring, IParam* >::iterator		ItPostType;

public:
	NCenter( ) 
	{
	
	}

	~NCenter( ) 
	{
		removePosts();
		removeObservers();
	}

	template < class T >
	bool addObserver( std::wstring name, T* type, typename Observer< T >::Func func )
	{
		Observer< T >* obr = new Observer< T >( type, func );

		std::pair< std::wstring, IObserver* > p( name, obr );
		
		_observers.insert( p );
		
		return true;
	}

	void removeObservers( std::wstring name )
	{
		if ( _observers.size() )
		{
			ItObsType upper = _observers.upper_bound( name );
			ItObsType lower = _observers.lower_bound( name );

			for ( ItObsType it = lower; it != upper; ++it )
			{
				delete ( *it ).second;
			}
		
			_observers.erase( lower, upper );
		}
	}

	void removeObservers( )
	{
		if ( _observers.size() )
		{
			for ( ItObsType it = _observers.begin(); it != _observers.end(); ++it )
			{
				delete ( *it ).second;
			}

			_observers.clear( );
		}
	}

	void removePosts()
	{
		if ( _posts.size() )
		{
			for ( ItPostType it = _posts.begin(); it != _posts.end(); ++it )
			{
				delete ( *it ).second;
			}

			_posts.clear( );
		}
	}

	void post( std::wstring name, IParam* param )
	{
		std::pair< std::wstring, IParam* > p( name, param );
		
		_posts.insert( p );
	}

	void operator () ( )
	{
		for ( ItPostType it = _posts.begin(); it != _posts.end(); ++it )
		{
			ItObsType upper = _observers.upper_bound( it->first );
			ItObsType lower = _observers.lower_bound( it->first );

			// need to fix on dynamic ( add remove ) _observers during one loop
			for ( ItObsType iit = lower; iit != upper; ++iit )
			{
				if ( it->first == iit->first )
				{
					( *( iit->second ) )( it->second );
				}
			}
		}
		
		removePosts();
	}

	void execute( )
	{
		this->operator()( );
	}

private:
	ObsType		_observers;
	PostType	_posts;
};

#endif